package com.hubiao.pro.common.utils;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Random;
import java.util.UUID;

/**
 * Description
 *
 * @author hubiao
 * @since 2021-01-29 17:41
 */
public class GenerateUUID {

    private RedisTemplate<String, Serializable> redisTemplate;

    public static String getOrderIdPrefix(LocalDateTime now) {
        return now.format( DateTimeFormatter.ofPattern( "yyyyMMddHHmmss" ) );
    }

    /**
     * 获取有过期时间的自增长ID
     *
     * @param key
     * @param expireTime
     * @return
     */
    public long generate(String key, Date expireTime) {
        RedisAtomicLong counter = new RedisAtomicLong( key, redisTemplate.getConnectionFactory() );
        Long expire = counter.getExpire();
        if (expire == -1) {
            counter.expireAt( expireTime );
        }
        return counter.incrementAndGet();
    }

    /**
     * 获取唯一Id
     *
     * @param key
     * @param hashKey
     * @param delta   增加量（不传采用1）
     * @return
     */
    public Long incrementHash(String key, String hashKey, Long delta) {
        try {
            if (null == delta) {
                delta = 1L;
            }
            return redisTemplate.opsForHash().increment( key, hashKey, delta );
        } catch (Exception e) {//redis宕机时采用uuid的方式生成唯一id
            int first = new Random( 10 ).nextInt( 8 ) + 1;
            int randNo = UUID.randomUUID().toString().hashCode();
            if (randNo < 0) {
                randNo = -randNo;
            }
            return Long.valueOf( first + String.format( "%16d", randNo ) );
        }
    }

    public String generateOrderId() {
        //生成id为当前日期（yyMMddHHmmss）+6位（从000000开始不足位数补0）
        LocalDateTime now = LocalDateTime.now();
        //生成yyyyMMddHHmmss
        String orderIdPrefix = getOrderIdPrefix( now );
        String orderId = orderIdPrefix + String.format( "%1$06d", generate( orderIdPrefix, getExpireAtTime( now ) ) );
        return orderId;

    }

    public Date getExpireAtTime(LocalDateTime now) {
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = now.plusSeconds( 20 );
        ZonedDateTime zdt = localDateTime.atZone( zoneId );
        Date date = Date.from( zdt.toInstant() );
        return date;
    }

}
